home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / b / b.lha / B / src / bed / eval.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-24  |  4.0 KB  |  181 lines

  1. /* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1984. */
  2. static char rcsid[] = "$Header: eval.c,v 2.3 84/07/19 11:47:18 guido Exp $";
  3.  
  4. /*
  5.  * B editor -- Width attribute evaluation.
  6.  */
  7.  
  8. #include "b.h"
  9. #include "node.h"
  10. #include "gram.h"
  11. #include "eval.h"
  12.  
  13.  
  14. /*
  15.  * The following convention is used throughout the editor to indicate
  16.  * the sizes of objects.
  17.  * - A zero or positive `width' value means the object contains no
  18.  *   linefeeds.  The width is counted in characters.
  19.  * - A negative `width' means the object (or its children) contains
  20.  *   at leasty one linefeed (return is treated as a linefeed here).
  21.  *   The number of linefeeds is -width.
  22.  *   There is no indication whether the object fits on that number of
  23.  *   physical lines, as logical lines may have arbitrary length.
  24.  *
  25.  * For coordinates the following convention is used.
  26.  * (Note that, in accordance to the convention in curses(3), the
  27.  * `y' coordinate always precedes the `x' coorxdinate.)
  28.  * - `Y' is the line number, counted from the beginning of the unit.
  29.  *   These are logical lines rather than physical lines.
  30.  *   The first line has line number 0.
  31.  * - `X' is the column number.  The first column is 0.  For x < 0,
  32.  *   see the important notice below.
  33.  * - `Level' is the indentation level, indicating where a new line
  34.  *   would start if inserted at the current position.
  35.  *   The initial `x' position of such a line is `level*TABS'.
  36.  *
  37.  * ***** IMPORTANT NOTICE *****
  38.  * A special case is x = -1.  This means that the current x position is
  39.  * unknown.  Further output on the same line is suppressed, until a
  40.  * linefeed is encountered.  This feature is necessary because while
  41.  * calculating coordinates, when an object has width < 0, only the y
  42.  * coordinate of the end of that object is known.  In this case, the
  43.  * next non-empty object MUST START WITH A LINEFEED, or it will not
  44.  * be visible on the screen (in practice, a space is sometimes present
  45.  * in the parse tree which is not shown then).
  46.  */
  47.  
  48.  
  49. /*
  50.  * Compute the (y, x) coordinates and indent level just before
  51.  * the beginning of the j'th child, if the current node starts
  52.  * at the initial values of (y, x) and level.
  53.  */
  54.  
  55. Visible Procedure
  56. evalcoord(n, jch, py, px, plevel)
  57.     register node n;
  58.     register int jch;
  59.     int *py;
  60.     int *px;
  61.     int *plevel;
  62. {
  63.     node nn;
  64.     register int i;
  65.     register string *rp = noderepr(n);
  66.     register int k;
  67.     register int y = 0;
  68.     int x = *px;
  69.     int level = *plevel;
  70.     int nch = Type(n) == Tex ? 0 : nchildren(n);
  71.  
  72.     if (jch > nch)
  73.         jch = nch+1;
  74.     for (i = 0; i < jch; ++i) {
  75.         if (i) {
  76.             nn = child(n, i);
  77.             k = width(nn);
  78.             if (k < 0) {
  79.                 y += -k;
  80.                 x = k;
  81.             }
  82.             else if (x >= 0)
  83.                 x += k;
  84.         }
  85.         k = Fwidth(rp[i]);
  86.         if (k < 0) {
  87.             y += -k;
  88.             x = rp[i][0] == '\r' ? 0 : TABS*level;
  89.             x += strlen(rp[i]) - 1;
  90.         }
  91.         else {
  92.             if (x >= 0)
  93.                 x += k;
  94.             if (rp[i]) {
  95.                 if (rp[i][k] == '\t')
  96.                     ++level;
  97.                 else if (rp[i][k] == '\b')
  98.                     --level;
  99.             }
  100.         }
  101.     }
  102.  
  103.     *py += y;
  104.     *px = x;
  105.     *plevel = level;
  106. }
  107.  
  108.  
  109. /*
  110.  * Yield the width of a piece of fixed text as found in a node's repr,
  111.  * excluding \b or \t.  If \n or \r is found, -1 is returned.
  112.  * It assumes that \n or \r only occur as first
  113.  * character, and \b or \t only as last.
  114.  */
  115.  
  116. Visible int
  117. fwidth(str)
  118.     register string str;
  119. {
  120.     register int c;
  121.     register int n = 0;
  122.  
  123.     if (!str)
  124.         return 0;
  125.     c = str[0];
  126.     if (c == '\r' || c == '\n')
  127.         return -1;
  128.     for (; c; c = *++str)
  129.         ++n;
  130.     if (n > 0) {
  131.         c = str[-1];
  132.         if (c == '\t' || c == '\b')
  133.             --n;
  134.     }
  135.     return n;
  136. }
  137.  
  138.  
  139. /*
  140.  * Evaluate the width of node n, assuming the widths of its children
  141.  * have correctly been calculated.
  142.  */
  143.  
  144. Visible int
  145. evalwidth(n)
  146.     register node n;
  147. {
  148.     register int w;
  149.     register int i;
  150.     register string *rp;
  151.     register int y = 0;
  152.     register int x = 0;
  153.     register int nch;
  154.     register node nn;
  155.  
  156.     rp = noderepr(n);
  157.     nch = Type(n) == Tex ? 0 : nchildren(n);
  158.     for (i = 0; i <= nch; ++i) {
  159.         if (i) {
  160.             nn = child(n, i);
  161.             w = width(nn);
  162.             if (w < 0) {
  163.                 y += -w;
  164.                 x = w;
  165.             }
  166.             else
  167.                 x += w;
  168.         }
  169.         w = Fwidth(rp[i]);
  170.         if (w < 0) {
  171.             y += -w;
  172.             x = 0;
  173.         }
  174.         else
  175.             x += w;
  176.     }
  177.     if (y > 0)
  178.         return -y;
  179.     return x;
  180. }
  181.